/* 
 * File:   Platform.cpp
 * Author: Aaron
 * 
 * Created on 19. Februar 2011, 15:14
 */


// -- Includes
#include "Platform.hpp"
#include "NoDefaultDeviceException.hpp"
#include <CL/cl.hpp>


namespace OpenCLWrapping
{
    Platform::Platform(const cl::Platform& _impl) :
        m_Impl(new cl::Platform(_impl))
    {
    }

    Platform::Platform(const Platform& _orig) :
        m_Impl(new cl::Platform(*_orig.getImpl()))
    {
    }

    Platform::~Platform()
    {
        delete m_Impl;
    }

    Platform& Platform::operator =(const Platform& _other)
    {
        // -- Verify that's not a self-assignment
        if (this->getImpl() != _other.getImpl())
        {
            delete m_Impl;
            m_Impl = new cl::Platform(*_other.getImpl());
        }

        return *this;
    }

    string Platform::getName() const
    {
        string ret;
        if (this->getImpl()->getInfo(CL_PLATFORM_NAME, &ret) != CL_SUCCESS)
        { 
            ret = "";
        }

        return ret;
    }

    string Platform::getVendor() const
    {
        string ret;
        if (this->getImpl()->getInfo(CL_PLATFORM_VENDOR, &ret) != CL_SUCCESS)
        {
            ret = "";
        }

        return ret;
    }

    Device Platform::getDefaultDevice() const
    {
        vector<Device> defaultDevice = this->getDevices(DeviceType::Default);
        if (defaultDevice.size() > 0)
        {
            return defaultDevice[0];
        }
        else
        {
            throw NoDefaultDeviceException();
        }
    }

    vector<Device> Platform::getDevices() const
    {
        return this->getDevices(DeviceType::All);
    }

    vector<Device> Platform::getDevices(DeviceType::DeviceType _types) const
    {
        // -- Convert enum bitfield to OpenCL device type bitfield
        cl_device_type clDevTypes = _types;
        
        // -- Fill result
        vector<Device> ret;
        vector<cl::Device> implDevices;
        if (this->getImpl()->getDevices(clDevTypes, &implDevices) == CL_SUCCESS)
        {
            for (int i = 0; i < implDevices.size(); ++i)
            {
                ret.push_back(Device(implDevices[i]));
            }
        }

        return ret;
    }

    vector<Platform> Platform::getPlatforms()
    {
        vector<Platform> ret;

        // -- Fill result
        vector<cl::Platform> implPlatforms;
        if (cl::Platform::get(&implPlatforms) == CL_SUCCESS)
        {
            for (int i = 0; i < implPlatforms.size(); ++i)
            {
                ret.push_back(Platform(implPlatforms[i]));
            }
        }

        return ret;
    }

    cl::Platform* Platform::getImpl()
    {
        return m_Impl;
    }

    const cl::Platform* Platform::getImpl() const
    {
        return m_Impl;
    }
}

